package com.example.exception;

import com.example.constant.Constant;
import com.example.constant.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.reactive.function.server.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.HashMap;
import java.util.Map;

public class GlobalExceptionHandler extends DefaultErrorWebExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    public GlobalExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    /**
     * 返回响应状态为200
     */
    @Override
    protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
        return HttpStatus.OK;
    }

    /**
     * 返回的错误信息
     *
     * @param request
     * @param includeStackTrace
     * @return
     */
    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        Throwable ex = this.getError(request);

        String transid = request.exchange().getAttribute(Constant.TRANS_ID);

        Map<String, Object> result = new HashMap<>();
        if (ex instanceof ResponseStatusException && HttpStatus.NOT_FOUND.equals(((ResponseStatusException) ex).getStatus())) {
            logger.error("[{}] 404 error, exception:{}", transid, ex);
            result.put("status", ErrorCode.ERROR_404.getCode());
            result.put("msg", ErrorCode.ERROR_404.getMsg());
        } else if (ex instanceof AuthenticationException) {
            logger.error("[{}] 401 error, exception:{}", transid, ex);
            result.put("status", ErrorCode.ERROR_401.getCode());
            result.put("msg", "授权失败！");
        } else {
            // 其它异常统一返回ERR19999
            logger.error("[{}] error, exctption:{}, error message:{}", transid, ex, ex.getMessage());
            result.put("status", ErrorCode.ERROR_500.getCode());
            result.put("msg", ErrorCode.ERROR_500.getMsg());
        }

        ex.printStackTrace();
        return result;
    }

    /**
     * 指定响应处理方法为JSON处理的方法
     */
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }
}
